package com.its.service.impl;

import com.its.pojo.LoginUser;
import com.its.pojo.User;
import com.its.mapper.UserMapper;
import com.its.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.its.util.JJwtUtil;
import com.its.util.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 28691
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private  UserMapper userMapper;
    @Autowired
    private  AuthenticationManager authenticationManager;

    @Autowired
    private RedisTemplate redisTemplate;
//    @Autowired
//    public UserServiceImpl(UserMapper userMapper, AuthenticationManager authenticationManager) {
//        this.userMapper = userMapper;
//        this.authenticationManager = authenticationManager;
//    }

    @Override
    public Result login(User user ,String addr) {
        Object object = redisTemplate.opsForValue().get("lock:" + addr);// 设置锁
        // 验证码次数超出上限后处理
        if (Objects.nonNull(object)){
            Integer number = (int) object;
            if (number>5){
                return  Result.error().message("验证码错误已到达上限，稍后在登陆。");
            }
        }
        Object o = redisTemplate.opsForValue().get(addr); // 获取验证码
        if (Objects.isNull(o)){
            return Result.error().message("验证码失效，请重新输入");
        }
        String redis_code = (String)o;
        System.out.println("code:"+user.getCode());
        if (!redis_code.equalsIgnoreCase(user.getCode())) {
            int num = 1; // 设置锁初始值
            Object object1 = redisTemplate.opsForValue().get("lock:" + addr);
            if (Objects.isNull(object1)){
                redisTemplate.opsForValue().set("lock:"+addr,1,10, TimeUnit.MINUTES); // 创建锁
            }else {
                redisTemplate.opsForValue().increment("lock:"+addr); // 锁值自增1
                num = (int) redisTemplate.opsForValue().get("lock:"+addr);
            }
            // 处理当前验证码错误次数过多锁定登录状态
            if (num >= 5){
                return  Result.error().message("验证码错误，已达到最大次数请十分钟之后在登陆。");
            }
            return Result.error().message("验证码错误，请重新输入");
        }

        try {
            // 构建认证对象
            // 创建身份令牌
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
            // 验证身份令牌
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authenticate)) {
                return Result.error().message("登录失败");
            }
            //使用UUID 作为存入Redis的key，防止用户退出后，旧的token还可以继续使用
            String uuid = UUID.randomUUID().toString();
            String token = JJwtUtil.getJwtToken(uuid);
            Map<String, String> map = new HashMap <>();
            map.put("token", token);
            redisTemplate.opsForValue().set(uuid, authenticate.getPrincipal(),7,TimeUnit.DAYS);
            //切记token信息一定需要返回给前端
            return Result.ok().data(token).message("登录成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().message("登录失败: " + e.getMessage());
        }
    }


    @Override
    public Result queryUserInfo(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)){
            return Result.error().message("令牌已过期或失效，请重新登录！");
        }
        String uuid = JJwtUtil.getMemberIdByJwtToken(token);
        Object object = redisTemplate.opsForValue().get(uuid);
        if (Objects.isNull(object)){
            return Result.error().message("您目前尚未登录");
        }
        LoginUser loginUser = (LoginUser)object;
        User user = loginUser.getUser();
        // 脱敏
        user.setPassword("***********");
        user.setId(null);
        return Result.ok().data(user).message("查询成功");
    }
}
